package algo3.algocity.modelo.mapa;

import java.util.ArrayList;
import java.util.Iterator;

import algo3.algocity.modelo.catastrofes.*;
import algo3.algocity.modelo.conectores.LineaDeTension;
import algo3.algocity.modelo.conectores.Ruta;
import algo3.algocity.modelo.conectores.TuberiaDeAgua;
import algo3.algocity.modelo.construibles.EstacionDeBomberos;
import algo3.algocity.modelo.excepciones.*;
import algo3.algocity.modelo.interfaces.*;

public class Mapa {

	private int ancho;
	private int altura;
	private ArrayList<ArrayList<Hectarea>> mapa = new ArrayList<ArrayList<Hectarea>>();
	private ArrayList<MiniConstruccion> miniConstrucciones = new ArrayList<MiniConstruccion>(); 
	private ArrayList<MegaConstruccion> megaConstrucciones = new ArrayList<MegaConstruccion>(); 
	private ArrayList<EstacionDeBomberos> bomberos = new ArrayList<EstacionDeBomberos>();
	
	public Mapa(){
		
		this.altura = 100;
		this.ancho = 100;
		this.crearMapa();
		this.agregarAguaAlMapa();
	}
		
	public int obtenerAncho(){
		
		return this.ancho;
	}
	
	public int obtenerAltura(){
		
		return this.altura; 
	}
	
	public ArrayList<MegaConstruccion> obtenerMegaConstrucciones() {
		
		return this.megaConstrucciones;
	}
	
	public ArrayList<MiniConstruccion> obtenerMiniConstrucciones() {
		
		return this.miniConstrucciones;
	}
	
	private void crearMapa(){
		
		int fila = 0;
		int columna = 0;
		
		while( fila < this.altura ){
          			
			ArrayList<Hectarea> filasMapa = new ArrayList<Hectarea>(); 
	        while(columna < this.ancho){
	        	
	        	agregarHectarea(filasMapa,fila,columna);
	            columna++; 
	        }	
		   
	        this.mapa.add(filasMapa);
		    fila++;
		    columna = 0;	
		}
	} 
	
	private void agregarHectarea(ArrayList<Hectarea> sectorDelMapa,int fila,int columna){
		
		Tierra porcionDeTierra = new Tierra();
		Coordenada coordenada = new Coordenada(fila,columna);
		Hectarea unaHectarea = new Hectarea(porcionDeTierra,coordenada);
    	sectorDelMapa.add(unaHectarea);
	}

	 public Hectarea obtenerUnSectorDelMapa(int fila, int columna){
	    	
		 return this.mapa.get(fila).get(columna);
	}

	public void construirMegaConstruccion(MegaConstruccion unaConstruccion,Coordenada coordenada) throws NoSePuedeEdificarEnEsaZonaException {
		 
		     int fila = coordenada.obtenerPosicionY();
		     int columna = coordenada.obtenerPosicionX();
		
		     if (unaConstruccion.obtenerTipoDeSuelo() == this.obtenerUnSectorDelMapa(fila, columna).obtenerTipoDeSuelo()) {
		    	 this.megaConstrucciones.add(unaConstruccion);	
		    	 unaConstruccion.establecerHectareaALaQuePertenece(this.obtenerUnSectorDelMapa(fila, columna));
		     } else {
		    	 NoSePuedeEdificarEnEsaZonaException excepcion = new NoSePuedeEdificarEnEsaZonaException();
		    	 throw excepcion;
		     }
	}

	public void construirEstacionDeBomberos(EstacionDeBomberos bomberos,Coordenada coordenada) throws NoSePuedeEdificarEnEsaZonaException {
		
		int fila = coordenada.obtenerPosicionY();
	    int columna = coordenada.obtenerPosicionX();
	
		if (bomberos.obtenerTipoDeSuelo() == this.obtenerUnSectorDelMapa(fila, columna).obtenerTipoDeSuelo()) {
			this.bomberos.add(bomberos);	
	    	 bomberos.establecerHectareaALaQuePertenece(this.obtenerUnSectorDelMapa(fila, columna));
	     } else {
	    	 NoSePuedeEdificarEnEsaZonaException excepcion = new NoSePuedeEdificarEnEsaZonaException();
	    	 throw excepcion;
	     }
	}
	
	public ArrayList<EstacionDeBomberos> obtenerEstacionDeBomberos() {
		
		return this.bomberos;
	}
	
	public boolean verificarSiMegaConstruccionSeEncuentraEnElMapa(Construccion unaConstruccion) {
		
		 Iterator<MegaConstruccion> iterador = this.megaConstrucciones.iterator(); 
		  
	     while(iterador.hasNext()) {
		 
		    Construccion construccionActual = iterador.next();
	     
		    if (construccionActual == unaConstruccion) return true;
		 
	     }
	     return false;
	}
	
	public void construirLineaDeTension(LineaDeTension unaLineaDeTension, Coordenada coordenada) throws NoSePuedeEdificarEnEsaZonaException{
		
		int fila = coordenada.obtenerPosicionY();
	    int columna = coordenada.obtenerPosicionX();
		if((this.mapa.get(fila).get(columna).obtenerTipoDeSuelo() == unaLineaDeTension.obtenerTipoDeSuelo())){
				//&& (this.mapa.get(fila).get(columna).obtenerMegaConstruccion()!= null)){
				//&&(buscadorDeLineasDeTensionContiguas(unaLineaDeTension, fila, columna))){
			
				unaLineaDeTension.establecerHectareaALaQuePertenece(this.obtenerUnSectorDelMapa(fila, columna));
				this.miniConstrucciones.add(unaLineaDeTension);
				this.obtenerUnSectorDelMapa(fila,columna).construirMiniConstruccion(unaLineaDeTension);
		    }
		
		else{ NoSePuedeEdificarEnEsaZonaException excepcion = new NoSePuedeEdificarEnEsaZonaException();
		 	  throw excepcion;
			}
		}
	
	public void construirTuberiaDeAgua(TuberiaDeAgua unaTuberia,Coordenada coordenada) throws NoSePuedeEdificarEnEsaZonaException{
		
		int fila = coordenada.obtenerPosicionY();
	    int columna = coordenada.obtenerPosicionX();
		if((this.mapa.get(fila).get(columna).obtenerMiniConstruccion() !=null )){
				//&&(buscadorDeTuberiasDeAguaContiguas(unaTuberia, fila,columna))){
		
			unaTuberia.establecerHectareaALaQuePertenece(this.obtenerUnSectorDelMapa(fila, columna));
			this.miniConstrucciones.add(unaTuberia);
			this.obtenerUnSectorDelMapa(fila, columna).construirMiniConstruccion(unaTuberia);
		}
	
		else{  NoSePuedeEdificarEnEsaZonaException excepcion = new NoSePuedeEdificarEnEsaZonaException();
	 	  	   throw excepcion;
			}
	}

/*	
	public ArrayList<Hectareas> buscar(MiniConstruccion unaMiniConstruccion,int y,int x){
		
		ArrayList<Hectareas> parcelasEncontradas =  new ArrayList<Hectareas>();
		
		if(unaMiniConstruccion.verificarSiHayConexion(this.mapa.get(y+1).get(x))){
			parcelasEncontradas.add(this.mapa.get(y+1).get(x));	
		}
			
		if(unaMiniConstruccion.verificarSiHayConexion(this.mapa.get(y-1).get(x))){
			parcelasEncontradas.add(this.mapa.get(y-1).get(x));	
		}
			
		if(unaMiniConstruccion.verificarSiHayConexion(this.mapa.get(y).get(x+1))){
			parcelasEncontradas.add(this.mapa.get(y).get(x+1));	
		}
			
		if(unaMiniConstruccion.verificarSiHayConexion(this.mapa.get(y).get(x-1))){
			parcelasEncontradas.add(this.mapa.get(y).get(x-1));	
		}
			
	    return parcelasEncontradas;
	}
	
	public boolean buscardorDeLineasDeTensionContiguas(LineaDeTension unaLineaDeTension, int y, int x){
	  
		  ArrayList<Hectareas> parcelasEncontradas; 
		  parcelasEncontradas = buscar(unaLineaDeTension,y,x);
		  
		  if(!parcelasEncontradas.isEmpty()){
			  
			  for(Hectareas parcela: parcelasEncontradas){
				  
				  if ( ((LineaDeTension) parcela.obtenerConstruccion()[1]).estaConectadoAUnSuministroElectrico())
					 if(!unaLineaDeTension.estaConectadoAUnSuministroElectrico())
						 unaLineaDeTension.conectarAElectrificable((Electrificable) parcela.obtenerConstruccion()[1]);
					 else {return false;}
				
				  else {((LineaDeTension) parcela.obtenerConstruccion()[1]).conectarAElectrificable(unaLineaDeTension);}
			  }
		  }
		  return true;
	}
	
	public boolean buscadorDeTuberiasDeAguaContiguas(TuberiaDeAgua unaTuberia,int y, int x){
		  
		  ArrayList<Hectareas> parcelasEncontradas; 
		  parcelasEncontradas = buscar(unaTuberia,y,x);
		  
		  if(!parcelasEncontradas.isEmpty()){
			  
			  for(Hectareas parcela: parcelasEncontradas){
				  
				  if ( ((TuberiaDeAgua) parcela.obtenerConstruccion()[2]).estaConectadoAUnSuministroDeAgua())
					  if(!unaTuberia.estaConectadoAUnSuministroDeAgua())
						  unaTuberia.conectarAEntubable((Entubable) parcela.obtenerConstruccion()[2]);
					  
					  else {return false;}
				  
				  else {((TuberiaDeAgua) parcela.obtenerConstruccion()[2]).conectarAEntubable(unaTuberia);}
			  }
		  }
		  return true;
	}*/

	private void agregarAguaAlMapa(){
		
		for(int columna = 5;columna < 35; columna++ ){
		
			for(int fila = 65; fila < 80 ; fila++){
				Agua porcionDeAgua = new Agua();
				Coordenada coordenada = new Coordenada(fila,columna);
				Hectarea unaParcela = new Hectarea(porcionDeAgua,coordenada);
				this.mapa.get(fila).set(columna,unaParcela);
			}
		}
	}

	public void agregarRuta(Ruta unaRuta,Coordenada coordenada) {
		
		int fila = coordenada.obtenerPosicionX();
		int columna = coordenada.obtenerPosicionY();
		unaRuta.establecerHectareaALaQuePertenece(this.obtenerUnSectorDelMapa(fila, columna));
		
		this.miniConstrucciones.add(unaRuta);
	    
		this.obtenerUnSectorDelMapa(fila, columna).construirMiniConstruccion(unaRuta);
	}
	
	public void crearCatastrofe(Godzilla godzilla) {
		
		int fila = godzilla.obtenerFila();
	    int columna = godzilla.obtenerColumna();
		this.megaConstrucciones.add(godzilla);
		godzilla.establecerHectareaALaQuePertenece(obtenerUnSectorDelMapa(fila, columna));
	}
	
	public void crearCatastrofe(Terremoto terremoto,Coordenada coordenada) {
		
		int fila = coordenada.obtenerPosicionY();
	    int columna = coordenada.obtenerPosicionX();
	    this.megaConstrucciones.add(terremoto);	
		terremoto.establecerHectareaALaQuePertenece(obtenerUnSectorDelMapa(fila, columna));
	}
	
}